package ui;

import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.log4j.Logger;

import controller.GroupMsgController;
import controller.GroupShakeController;
import controller.PrivateMsgController;
import controller.PrivateShakeController;
import controller.QuitController;

public class ChatWin extends JFrame {
	
	private static final Logger LOGGER = Logger.getLogger(ChatWin.class);

	private static final long serialVersionUID = 1L;
	private String userName;

	private JTextArea chatArea;
	private JScrollPane chatPane;
	private JTextArea msgInputArea;
	private JButton vibrateBtn;
	private JButton sendBtn;
	private JList<String> userList;
	private DefaultListModel<String> users;
	private JScrollPane listPane;
	
	// decide whether user can send message. will become FALSE if server crashed;
	private boolean canSendMsg;
	
	public ChatWin() {
		this.setSize(640, 480);
//		this.setTitle("Chating room");
		this.setResizable(false);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		
		init();
		addEvent();
		this.setVisible(false);
	}
	
	public void setCanSendMsg(boolean canSendMsg) {
		this.canSendMsg = canSendMsg;
	}

	public String getUserName() {
		return userName;
	}
	
	public void setUserName(String userName){
		this.userName = userName;
	}

	public JTextArea getChatArea() {
		return chatArea;
	}
	
	public JList<String> getUserList() {
		return userList;
	}

	public DefaultListModel<String> getUsers() {
		return users;
	}
	
	public JScrollPane getChatPane() {
		return chatPane;
	}

	public void shake(){
		Point point = this.getLocation();
		for(int i=20; i>0; i--){ //i为抖动大小
			for(int j=50; j>0; j--){	//j为抖动次数
				point.y += i;
				this.setLocation(point);
				point.x += i;
				this.setLocation(point);
                point.y -= i;
                this.setLocation(point);
                point.x -= i;
                this.setLocation(point);
			}
		}
	}

	private void init() {
		this.setLayout(null);
		
		canSendMsg = true;
		
		chatArea = new JTextArea();
		chatPane = new JScrollPane(chatArea);
		msgInputArea = new JTextArea();
		vibrateBtn = new JButton("VIBRATE");
		sendBtn = new JButton("SEND");
		users = new DefaultListModel<>();
		userList = new JList<>(users);
		listPane = new JScrollPane(userList);
		
		chatPane.setBounds(0, 0, 490, 380);

		chatArea.setEditable(false);
		chatArea.setMargin(new Insets(5, 5, 5, 5));
		chatArea.setFont(new Font(null, NORMAL, 15));
		chatArea.setLineWrap(true);
		chatArea.setWrapStyleWord(true);
				
		chatPane.getViewport().add(chatArea, null);
		
		msgInputArea.setBounds(0, 380, 390, 100);
		msgInputArea.setMargin(new Insets(5, 5, 5, 5));
		msgInputArea.setFont(new Font(null, Font.ITALIC, 16));
		msgInputArea.setLineWrap(true);
		msgInputArea.setWrapStyleWord(true);
		
		vibrateBtn.setBounds(390, 380, 100, 37);
		sendBtn.setBounds(390, 416, 100, 37);
		listPane.setBounds(490, 0, 150, 480);
		userList.setBounds(490, 0, 150, 480);
		userList.setFixedCellHeight(30);
		userList.setFont(new Font(null, Font.CENTER_BASELINE, 15));
		userList.setForeground(new Color(70,130,180));
		
		this.add(chatPane);
		this.add(msgInputArea);
		this.add(vibrateBtn);
		this.add(sendBtn);
		this.add(listPane);
	}
	
	private void addEvent() {
		sendBtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				sendMessageInTextArea();
			}
		});
		
		msgInputArea.addKeyListener(new KeyListener() {
			
			public void keyTyped(KeyEvent e) {
			}
			public void keyReleased(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					sendMessageInTextArea();
				}
			}
			
			public void keyPressed(KeyEvent e) {
			}
		});
		
		/**
		 * vibration
		 */
		vibrateBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				
				if (!canSendMsg) {
					JOptionPane.showMessageDialog(ChatWin.this, "The server is crashed!", "Error", JOptionPane.ERROR_MESSAGE);
					return;
				}
				
				String from = userName;
				String to = userList.getSelectedValue();
				
				try {
					if (userList.getSelectedIndex() == 0) {
						new GroupShakeController().control(from);
					} else {
						new PrivateShakeController().control(from, to);
					}
					
					SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
					String timeString = sdf.format(Calendar.getInstance().getTime());
					chatArea.append("\n [" + timeString + "] YOU shake " + (to == null ? "ALL" : to) + "!");
				} catch (IOException e1) {
//					e1.printStackTrace();
					LOGGER.error(e1.toString());
					JOptionPane.showMessageDialog(ChatWin.this, "The server is crashed!", "Error", JOptionPane.ERROR_MESSAGE);
				}
				
			}
		});
		
		// listen to closing button action
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e){
				String from = getUserName();
				try {
					if (!canSendMsg) {
						throw new IOException("Server crashed, close without sending quit request...");
					}
					
					new QuitController().control(from);
				} catch (IOException e1) {
//					e1.printStackTrace();
					LOGGER.error(e1.toString());
					
					// cannot connect to server. Exit the client
					ChatWin.this.dispose();
					System.exit(0);
				}
			  }
		});
		
		userList.addListSelectionListener(new ListSelectionListener() {
			
			@Override
			public void valueChanged(ListSelectionEvent e) {
				String name = userList.getSelectedValue();
				ChatWin.this.setTitle(userName + " -- Now talking to: " + name);
			}
		});
		
	}
	
	private void sendMessageInTextArea() {
		
		if (!canSendMsg) {
			JOptionPane.showMessageDialog(ChatWin.this, "The server is crashed!", "Error", JOptionPane.ERROR_MESSAGE);
			return;
		}
		
		String msg = msgInputArea.getText().trim();
		if (msg.isEmpty()) {
			JOptionPane.showMessageDialog(ChatWin.this, "Cannot send empty message!", "Error", JOptionPane.ERROR_MESSAGE);
			msgInputArea.setText(null);
			return;
		}
		
		String from = userName;
		String to = userList.getSelectedValue();
		
		try {
			if (userList.getSelectedIndex() == 0 || userList.getSelectedIndex() == -1) {
				new GroupMsgController().control(msg, from);
			} else {
				new PrivateMsgController().control(msg, from, to);
			}
			
			SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
			String timeString = sdf.format(Calendar.getInstance().getTime());
			chatArea.append("\n [" + timeString + "] YOU send to " + (to == null ? "ALL" : to) + ": " + msg);
			msgInputArea.setText(null);
			chatArea.setCaretPosition(chatArea.getText().length());
		} catch (IOException e1) {
//			e1.printStackTrace();
			LOGGER.error(e1.toString());
			JOptionPane.showMessageDialog(ChatWin.this, "The server is crashed!", "Error", JOptionPane.ERROR_MESSAGE);
//			msgInputArea.setText(null);
		}
		
	}
	
	public static void main(String[] args) throws Exception {
		new ChatWin();
	}
}
